package goods

import (
	"context"
	"net/http"

	"github.com/gin-gonic/gin"

	"mxshop-api/goods-web/api"
	goodsForm "mxshop-api/goods-web/forms/goods"
	"mxshop-api/goods-web/global"
	proto "mxshop-api/goods-web/proto/gen/v1"
	"mxshop-api/shared/utils"
)

func List(c *gin.Context) {
	var goodsFilter goodsForm.Filter
	err := c.ShouldBindQuery(&goodsFilter)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	GoodsClient := proto.NewGoodsClient(global.Conn)
	r, err := GoodsClient.GoodsList(context.Background(), &proto.GoodsFilterRequest{
		PriceMin:    goodsFilter.PriceMin,
		PriceMax:    goodsFilter.PriceMax,
		IsHot:       goodsFilter.IsHot,
		IsNew:       goodsFilter.IsNew,
		IsTab:       goodsFilter.IsTab,
		TopCategory: goodsFilter.TopCategory,
		Pages:       goodsFilter.Pages,
		PagePerNums: goodsFilter.PagePerNums,
		KeyWords:    goodsFilter.KeyWords,
		Brand:       goodsFilter.Brand,
	})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	var goodsList []gin.H
	for _, value := range r.Data {
		goodsList = append(goodsList, InfoGrpcToMap(value))
	}
	c.JSON(http.StatusOK, goodsList)
}

func Detail(c *gin.Context) {
	var goodsIns goodsForm.Goods
	err := c.ShouldBindUri(&goodsIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}
	r, err := proto.NewGoodsClient(global.Conn).GetGoodsDetail(
		context.Background(), &proto.GoodInfoRequest{Id: goodsIns.ID})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}
	c.JSON(http.StatusOK, InfoGrpcToMap(r))
}

func New(c *gin.Context) {
	var form goodsForm.Form
	err := c.ShouldBind(&form)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	resp, err := proto.NewGoodsClient(global.Conn).CreateGoods(
		context.Background(), &proto.CreateGoodsInfo{
			Name:            form.Name,
			GoodsSn:         form.GoodsSn,
			Stocks:          form.Stocks,
			MarketPrice:     form.MarketPrice,
			ShopPrice:       form.ShopPrice,
			GoodsBrief:      form.GoodsBrief,
			ShipFree:        *form.ShipFree,
			Images:          form.Images,
			DescImages:      form.DescImages,
			GoodsFrontImage: form.FrontImage,
			CategoryId:      form.CategoryId,
			BrandId:         form.Brand,
		})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	// 如何设置库存
	// TODO 商品的库存 - 分布式事务
	c.JSON(http.StatusCreated, resp)
}

func Update(c *gin.Context) {
	var goodsIns goodsForm.Goods
	var form goodsForm.Form

	err := c.ShouldBindUri(&goodsIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}
	err = c.ShouldBind(&form)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	_, err = proto.NewGoodsClient(global.Conn).UpdateGoods(context.Background(), &proto.CreateGoodsInfo{
		Id:              goodsIns.ID,
		Name:            form.Name,
		GoodsSn:         form.GoodsSn,
		Stocks:          form.Stocks,
		MarketPrice:     form.MarketPrice,
		ShopPrice:       form.ShopPrice,
		GoodsBrief:      form.GoodsBrief,
		ShipFree:        *form.ShipFree,
		Images:          form.Images,
		DescImages:      form.DescImages,
		GoodsFrontImage: form.FrontImage,
		CategoryId:      form.CategoryId,
		BrandId:         form.Brand,
	})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"msg": "更新成功",
	})
}

func UpdateStatus(c *gin.Context) {
	var goodsIns goodsForm.Goods
	var statusForm goodsForm.StatusForm

	err := c.ShouldBindUri(&goodsIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}
	err = c.ShouldBind(&statusForm)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	_, err = proto.NewGoodsClient(global.Conn).UpdateGoods(context.Background(), &proto.CreateGoodsInfo{
		Id:     goodsIns.ID,
		IsHot:  *statusForm.IsNew,
		IsNew:  *statusForm.IsNew,
		OnSale: *statusForm.OnSale,
	})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"msg": "更新成功",
	})
}

func Delete(c *gin.Context) {
	var goodsIns goodsForm.Goods
	err := c.ShouldBindUri(&goodsIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	_, err = proto.NewGoodsClient(global.Conn).DeleteGoods(context.Background(), &proto.DeleteGoodsInfo{
		Id: goodsIns.ID,
	})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.Status(http.StatusNoContent)
}

func InfoGrpcToMap(info *proto.GoodsInfoResponse) map[string]interface{} {
	var goodsMap = map[string]interface{}{
		"id":          info.Id,
		"name":        info.Name,
		"goods_brief": info.GoodsBrief,
		"desc":        info.GoodsDesc,
		"ship_free":   info.ShipFree,
		"images":      info.Images,
		"desc_images": info.DescImages,
		"front_image": info.GoodsFrontImage,
		"shop_price":  utils.PriceInt(info.ShopPrice).String(),
		"category": gin.H{
			"id":   info.Category.Id,
			"name": info.Category.Name,
		},
		"brand": gin.H{
			"id":   info.Brand.Id,
			"name": info.Brand.Name,
			"logo": info.Brand.Logo,
		},
		"is_hot":  info.IsHot,
		"is_new":  info.IsNew,
		"on_sale": info.OnSale,
	}
	return goodsMap
}
